package top.lingkang.cvdemo.test;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.image.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.opencv.videoio.VideoCapture;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author lingkang
 * @date 2021/12/28
 */
public class Demo02 extends Application {
    private static final int frameRate = 10;// 录制的帧率

    @Override
    public void start(Stage primaryStage) throws Exception {
        ImageView imageVideo = new ImageView();
        imageVideo.setFitWidth(800);
        imageVideo.setFitHeight(600);

        AnchorPane anchorPane = new AnchorPane();
        anchorPane.getChildren().add(imageVideo);
        primaryStage.setScene(new Scene(anchorPane));
        primaryStage.setHeight(600);
        primaryStage.setWidth(800);
        primaryStage.show();

        FrameGrabber grabber = new FFmpegFrameGrabber("desktop");
        grabber.setFormat("gdigrab");
        // 捕获指定区域，不设置则为全屏
        grabber.setFrameRate(frameRate);
        grabber.setImageHeight(600);
        grabber.setImageWidth(800);
        grabber.setOption("offset_x","200");
        //grabber.setOption("offset_y","200");
        grabber.start();
        VideoCapture videoCapture=new VideoCapture();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Platform.runLater(new Runnable() {// 无法在主线程更新UI，使用Platform.runLater
                    @Override
                    public void run() {
                        try {
                            //返回一帧
                            Frame frame = grabber.grabFrame();
                            // 观察可以怎么实现的
                            PixelReader pr = new FramePixelReader(frame);
                            Image image = new WritableImage(pr, frame.imageWidth, frame.imageHeight);
                            // 更新
                            imageVideo.setImage(image);
                        } catch (FrameGrabber.Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        }, 2000, 1000 / frameRate);
    }

    public static void main(String[] args) throws Exception {
        launch(args);
    }

    // 手动实现这个类 JavaFXFrameConverter.convert的底层实现
    class FramePixelReader implements PixelReader {

        Frame frame;

        FramePixelReader(Frame f) {
            this.frame = f;
        }

        @Override
        public PixelFormat getPixelFormat() {
            throw new UnsupportedOperationException("getPixelFormat not supported yet.");
        }

        @Override
        public int getArgb(int x, int y) {
            throw new UnsupportedOperationException("getArgb not supported yet.");
        }

        @Override
        public Color getColor(int x, int y) {
            throw new UnsupportedOperationException("getColor not supported yet.");
        }

        @Override
        public <T extends Buffer> void getPixels(int x, int y, int w, int h, WritablePixelFormat<T> pixelformat, T buffer, int scanlineStride) {
            int fss = frame.imageStride;
            if (frame.imageChannels != 3) {
                throw new UnsupportedOperationException("We only support frames with imageChannels = 3 (BGR)");
            }
            if (buffer instanceof ByteBuffer) {
                ByteBuffer bb = (ByteBuffer) buffer;
                ByteBuffer b = (ByteBuffer) frame.image[0];
                for (int i = y; i < y + h; i++) {
                    for (int j = x; j < x + w; j++) {
                        int base = 3 * j;
                        bb.put(b.get(fss * i + base));
                        bb.put(b.get(fss * i + base + 1));
                        bb.put(b.get(fss * i + base + 2));
                        bb.put((byte) 255);
                    }
                }

            } else throw new UnsupportedOperationException("We only support bytebuffers at the moment");
        }

        @Override
        public void getPixels(int x, int y, int w, int h, WritablePixelFormat<ByteBuffer> pixelformat, byte[] buffer, int offset, int scanlineStride) {
            throw new UnsupportedOperationException("getPixels<ByteBuffer> Not supported yet.");
        }

        @Override
        public void getPixels(int x, int y, int w, int h, WritablePixelFormat<IntBuffer> pixelformat, int[] buffer, int offset, int scanlineStride) {
            throw new UnsupportedOperationException("getPixels<IntBuffer>Not supported yet.");
        }

    }
}
